/*
 * fileup.c - EDB file upload
 * Clunix, cezanne@clunix.com, 2007.7
 *
 * Copyright (c) 2001-2007 by Clunix Inc. All Rights Reserved.
 */

#include "config.h"

#include "ecm.h"
#include "edb_p.h"
#include "edb_proto.h"

#define	UPDN_CHUNKSIZE	8192

edb_err_t
edb_file_upload(edb_t *ed, const char *src_path,
		ebc_ndid_t dst_ndid, const char *dst_path, edb_fileopt_t opt)
{
	int	fd;
	ecm_uint8	buf[UPDN_CHUNKSIZE];
	ecm_size_t	size;
	edb_file_id_t	fid;
	edb_err_t	err;

	if ((fd = ecm_open(src_path, ECM_O_RDONLY)) < 0)
		return -ERR_EDB_NOTEXIST;

	err = edb_file_open(ed, dst_ndid, dst_path, &fid, ECM_O_WRONLY);
	if (err != EDB_OK) {
		ecm_close(fd);
		return err;
	}

	while (ECM_TRUE) {
		size = UPDN_CHUNKSIZE;
		if (!ecm_read(fd, (char *)buf, &size)) {
			edb_file_close(ed, fid, ECM_FALSE);
			ecm_close(fd);
			return -ERR_EDB_GENERAL;
		}
		if (size == 0)
			break;
		err = edb_file_write(ed, fid, buf, size);
		if (err != EDB_OK) {
			edb_file_close(ed, fid, ECM_FALSE);
			ecm_close(fd);
			return err;
		}
	}
	edb_file_close(ed, fid, ECM_TRUE);
	ecm_close(fd);
	return EDB_OK;
}

static ECMBOOL
do_write(int fd, char *buf, ecm_size_t size)
{
	ecm_size_t	bufsize;

	bufsize = size;
again:
	if (!ecm_write(fd, (char *)buf, &bufsize))
		return ECM_FALSE;
	if (bufsize != size) {
		buf += bufsize;
		bufsize = size - bufsize;
		goto again;
	}
	return ECM_TRUE;
}

edb_err_t
edb_file_download(edb_t *ed, const char *dst_path,
		  ebc_ndid_t src_ndid, const char *src_path, edb_fileopt_t opt)
{
	int	fd;
	ecm_uint8	buf[UPDN_CHUNKSIZE];
	ecm_size_t	size;
	edb_file_id_t	fid;
	edb_err_t	err;

	if (ecm_creat(&fd, dst_path, ECM_P_RWUSR) != ECM_OK)
		return -ERR_EDB_INVALIDARG;

	err = edb_file_open(ed, src_ndid, src_path, &fid, ECM_O_RDONLY);
	if (err != EDB_OK) {
		ecm_close(fd);
		ecm_unlink(dst_path);
		return err;
	}

	while (ECM_TRUE) {
		size = UPDN_CHUNKSIZE;
		err = edb_file_read(ed, fid, buf, &size);
		if (err != EDB_OK) {
			ecm_close(fd);
			ecm_unlink(dst_path);
			return err;
		}
		if (size == 0)
			break;
		if (!do_write(fd, (char *)buf, size)) {
			edb_file_close(ed, fid, ECM_FALSE);
			ecm_close(fd);
			ecm_unlink(dst_path);
			return -ERR_EDB_GENERAL;
		}
	}
	edb_file_close(ed, fid, ECM_TRUE);
	ecm_close(fd);
	return EDB_OK;
}
